home *** CD-ROM | disk | FTP | other *** search
/ Revolution - Das Atari CD Magazin 1997 / Revolution - Das Atari CD Magazin 1.iso / software / anwendng / qed_397 / sourcen / windows.c < prev    next >
C/C++ Source or Header  |  1997-01-17  |  43KB  |  1,622 lines

  1. #include "global.h"
  2. #include "av.h"
  3. #include "comm.h"
  4. #include "desktop.h"
  5. #include "event.h"
  6. #include "fontsel.h"
  7. #include "icon.h"
  8. #include "magx.h"
  9. #include "makro.h"
  10. #include "menu.h"
  11. #include "obj.h"
  12. #include "options.h"
  13. #include "rsc.h"
  14. #include "scroll.h"
  15. #include "set.h"
  16. #include "windows.h"
  17.  
  18. VOID    clr_undo        (VOID);                /* aus CLIPBRD.H */
  19.  
  20. /*
  21.  * exportierte Variablen
  22.  */
  23.  
  24. GLOBAL WINDP     sel_window;        /* Zeiger auf selektiertes Fenster */
  25. GLOBAL SET        sel_objs;        /* Menge selektierter Objekte */
  26. GLOBAL BOOLEAN    all_iconified;
  27.  
  28. /****** DEFINES ************************************************************/
  29.  
  30. #ifndef WM_BOTTOMED
  31. #define WM_BOTTOMED            33
  32. #endif
  33.  
  34. #ifndef WF_ICONIFY
  35. #define WF_ICONIFY            26
  36. #define WF_UNICONIFY            27
  37. #define WF_UNICONIFYXYWH    28
  38. #endif
  39.  
  40.  
  41. #define MIN_WIDTH        (8 * sys_wchar)            /* Kleinste Breite */
  42. #define MIN_HEIGHT     (8 * sys_hchar)            /* Kleinste Höhe */
  43.  
  44. #define WORK_MOVED    0x01                /* Für Verschieben und Vergrößern */
  45. #define WORK_SIZED    0x02
  46.  
  47. #define MAX_WINDOW     19
  48.  
  49. /****** TYPES **************************************************************/
  50.  
  51. /****** VARIABLES **********************************************************/
  52.  
  53. LOCAL WINDOW    windrec[MAX_WINDOW];            /* Speicher für Fenster */
  54.  
  55. LOCAL RECT    border;                    /* für rc_first/next */
  56.  
  57. LOCAL WINDP    free_list;                /* ROOT der unbenutzten Fenster */
  58. LOCAL WINDP    used_list;                /* ROOT der benutzten Fenster */
  59. LOCAL WORD    age, top_handle;
  60.  
  61. LOCAL WINDP    icon_win;
  62. LOCAL WORD    opened_win[MAX_WINDOW];    /* Iconnummer der offen gewesenen Fenster
  63.                                                  * [0] enthält die Anzahl !!
  64.                                                  */
  65. /****** FUNCTIONS **********************************************************/
  66.  
  67. LOCAL VOID move_to_top    (WINDP window);
  68. LOCAL VOID move_to_end    (WINDP window);
  69. LOCAL VOID get_work        (WINDP window, RECT *new, WORD mode);
  70. LOCAL VOID do_arrow        (WINDP window, WORD dir, long delta);
  71. LOCAL VOID default_snap    (WINDP window, RECT *new, WORD mode);
  72.  
  73. /***************************************************************************/
  74.  
  75. VOID add_windinfo(WORD class, RECT *r, WORD icon_x, WORD icon_y, WORD init)
  76. {
  77.     WORD i;
  78.     WINDP window;
  79.  
  80.     switch (class)
  81.     {
  82.         case 2 : class = CLASS_EDIT; break;
  83.         case 3 : class = CLASS_CLIP; break;
  84.         case 4 : class = CLASS_PROJEKT; break;
  85.         case 5 : class = CLASS_TRASH; break;
  86.         default: return;
  87.     }
  88.     for (i=MAX_WINDOW,window=windrec; (--i)>=0; window++)
  89.     {
  90.         if (r==NULL)                        /* Nur Iconpos setzen */
  91.         {
  92.             if (window->icon_x==0 && window->icon_y==0 &&
  93.                  window->class==class)            /* Ohne Iconpos */
  94.             {
  95.                 window->icon_x = icon_x;
  96.                 window->icon_y = icon_y;
  97.                 break;
  98.             }
  99.         }
  100.         else
  101.         {
  102.             if (window->work.w == 0)                /* Ohne Info */
  103.             {
  104.                 window->class = class;
  105.                 window->work = *r;
  106.                 window->icon_x = icon_x;
  107.                 window->icon_y = icon_y;
  108.                 window->init = init;
  109.                 break;
  110.             }
  111.         }
  112.     }
  113. }
  114.  
  115. BOOLEAN get_windinfo(WORD *last, WORD *class, RECT *r, WORD *icon_x,
  116.                   WORD *icon_y, WORD *used)
  117. {
  118.     WORD    i, nr;
  119.     WINDP window;
  120.  
  121.     i = *last+1;
  122.     if (i >= age)
  123.         return FALSE;
  124. retry:
  125.    *used = 0;
  126.    nr = 1;
  127.     for (window = free_list; window != NULL && window->age != i; window = window->next)
  128.         ;
  129.     if (window == NULL)
  130.     {
  131.         for (window = used_list; window != NULL && window->age != i; window=window->next, nr++)
  132.             ;
  133.         if (window!=NULL)
  134.         {
  135.             *used = nr;
  136.         }
  137.     }
  138.     if (window==NULL || window->class==DESK || window->work.w==0)
  139.     {
  140.         i++;
  141.         if (i == age)
  142.             return FALSE;
  143.         goto retry;
  144.     }
  145.  
  146.     *r = window->work;
  147.     *icon_x = window->icon_x;
  148.     *icon_y = window->icon_y;
  149.     switch (window->class)
  150.     {
  151.         case CLASS_EDIT : *class = 2; break;
  152.         case CLASS_CLIP : *class = 3; break;
  153.         case CLASS_PROJEKT:*class = 4; break;
  154.         case CLASS_TRASH: *class = 5; break;
  155.     }
  156.     *last = i;
  157.     return TRUE;
  158. }
  159.  
  160. BOOLEAN rc_first(WORD wh, CONST RECT *b, RECT *r)
  161. {
  162.     border = *b;
  163.     if (!myrc_intersect(&desk,&border))            /* mit Bildschirm schneiden */
  164.         return FALSE;
  165.     wind_get (wh, WF_FIRSTXYWH, &r->x, &r->y, &r->w, &r->h);
  166.     while (r->w && r->h)
  167.     {
  168.         if (myrc_intersect (&border, r))            /* Schneide Rechtecke */
  169.             return TRUE;
  170.         wind_get (wh, WF_NEXTXYWH, &r->x, &r->y, &r->w, &r->h);
  171.     }
  172.     return FALSE;
  173. }
  174.  
  175. BOOLEAN rc_next(WORD wh, RECT *r)
  176. {
  177.     wind_get (wh, WF_NEXTXYWH, &r->x, &r->y, &r->w, &r->h);
  178.     while (r->w && r->h)
  179.     {
  180.         if (myrc_intersect (&border, r))            /* Schneide Rechtecke */
  181.             return TRUE;
  182.         wind_get (wh, WF_NEXTXYWH, &r->x, &r->y, &r->w, &r->h);
  183.     }
  184.     return FALSE;
  185. }
  186.  
  187. /************************************************************************/
  188. /* Suche nach Fenster                                                                     */
  189. /************************************************************************/
  190.  
  191. WINDP get_window (WORD link)
  192. {
  193.     WINDP w;
  194.  
  195.     for (w=used_list; w!=NULL ; w=w->next)
  196.     {
  197.         if (link==w->link) return (w);
  198.     }
  199.     return (NULL);
  200. } /* get_window */
  201.  
  202. /***************************************************************************/
  203. /* Suche Fenster von Fenster-Handle                                                        */
  204. /***************************************************************************/
  205.  
  206. WINDP find_window (WORD wh)
  207. {
  208.     WINDP w;
  209.  
  210.     /*
  211.      * Fenster 0 nur dann sinnvoll, wenn qed-Desktop aktiv.
  212.      * Sonst wird NULL geliefert, damit D&D zu Thing möglich wird!
  213.     */
  214.     if ((wh != 0) || ((wh == 0) && (!no_desktop)))
  215.     {
  216.         for (w=used_list; w!=NULL; w=w->next)
  217.         {
  218.             if (wh==w->handle) return (w);
  219.         }
  220.     }
  221.     return (NULL);
  222. } /* find_window */
  223.  
  224. /***************************************************************************/
  225. /* Suche oberstes Fenster                                                                    */
  226. /***************************************************************************/
  227.  
  228. WINDP top (VOID)
  229. {
  230.     WINDP w;
  231.  
  232.     for (w=used_list; w!=NULL && w->opened; w=w->next)
  233.         return w;
  234.     return NULL;
  235. }
  236.  
  237. VOID get_realtop(VOID)
  238. {
  239.     wind_get (0, WF_TOP, &top_handle);
  240. }
  241.  
  242. WINDP real_top (VOID)
  243. {
  244.     WINDP    window;
  245.  
  246.     window = top();
  247.     if (window==NULL) return NULL;
  248.     return ((window->handle==top_handle) ? window : NULL);
  249. }
  250.  
  251. BOOLEAN free_for_draw(WINDP window)
  252. {
  253.     RECT draw;
  254.  
  255.     if (rc_first(window->handle, &window->work, &draw))
  256.     {
  257.         if (window->work.w == draw.w && window->work.h == draw.h)
  258.             return TRUE;
  259.     }
  260.     return FALSE;
  261. }
  262.  
  263. /***************************************************************************/
  264. /* Zähle Anzahl vorhandener Fenster einer Klasse                                    */
  265. /***************************************************************************/
  266.  
  267. WORD num_windows (WORD class, WORD mode)
  268. {
  269.     WORD    num;
  270.     WINDP window;
  271.  
  272.     num = 0;
  273.     for (window=used_list; window!=NULL; window=window->next)
  274.     {
  275.         if (class==NIL || class==window->class)
  276.             if ((mode==SRCH_ANY) ||
  277.                  (!window->opened && mode==SRCH_CLOSED) ||
  278.                  ( window->opened && mode==SRCH_OPENED))
  279.             {
  280.                 num++;
  281.             }
  282.     }
  283.     return (num);
  284. } /* num_windows */
  285.  
  286. VOID get_all_windows (WORD class, WORD mode, VOID (*doit)(WINDP window))
  287. {
  288.     WINDP    window;
  289.  
  290.     for (window=used_list; window!=NULL; window=window->next)
  291.     {
  292.         if (class==NIL || class==window->class)
  293.             if ((mode==SRCH_ANY) ||
  294.                  (!window->opened && mode==SRCH_CLOSED) ||
  295.                  ( window->opened && mode==SRCH_OPENED))
  296.         {
  297.             (*doit)(window);
  298.         }
  299.     }
  300. } /* get_all_windows */
  301.  
  302. /***************************************************************************/
  303.  
  304. LOCAL VOID move_to_top (WINDP window)
  305. {
  306.     WINDP w;
  307.  
  308.     if (used_list==window) return;
  309.     for (w=used_list; w->next!=window; w=w->next) ;
  310.     w->next = window->next;
  311.     window->next = used_list;
  312.     used_list = window;
  313. } /* move_to_top */
  314.  
  315. /***************************************************************************/
  316.  
  317. LOCAL VOID move_to_end (WINDP window)
  318. {
  319.     WINDP w;
  320.  
  321.     if (used_list==window)
  322.         used_list = window->next;
  323.     else
  324.     {
  325.         for (w=used_list; w->next!=window; w=w->next) ;
  326.         w->next = window->next;
  327.     }
  328.     window->next = NULL;
  329.     if (used_list==NULL)
  330.         used_list = window;
  331.     else
  332.     {
  333.         for (w=used_list; w->next!=NULL; w=w->next) ;
  334.         w->next = window;
  335.     }
  336. } /* move_to_end */
  337.  
  338.  
  339. /***************************************************************************/
  340. /* Einschnappen des Fenster(inneren) auf bestimmte Grenzen                        */
  341. /* x : auf Bytegrenze (von work)                                                            */
  342. /* y : gerade             (von work)                                                            */
  343. /* w und h : vielfache von xfac und yfac    (von scroll)                            */
  344. /* new ist Innenbereich    (work)                                                            */
  345. /***************************************************************************/
  346.  
  347. LOCAL VOID snap_window(WINDP window, RECT *new, WORD mode)
  348. {
  349.     new->x = (new->x+4)&(~7);                                /* Byte Position */
  350.     new->y &= (~1);                                            /* gerade Position */
  351.  
  352.     if (mode&WORK_SIZED)
  353.     {
  354.         new->w = new->w-(new->w%window->xfac);
  355.         new->h = new->h-(new->h%window->yfac);
  356.     }
  357.  
  358.     if (window->snap != NULL)
  359.         (*window->snap) (window, new, mode);
  360. } /* snap_window */
  361.  
  362. /***************************************************************************/
  363. /* Setze Arbeitsbereich des Fensters                                                    */
  364. /* new: Aussenbereich des Fensters                                                        */
  365. /***************************************************************************/
  366.  
  367. LOCAL VOID test_work(RECT *new)
  368. {
  369.     /* Liegt und paßt das Fenster auf den Bildschirm */
  370.     if (new->y < desk.y)
  371.         new->y = desk.y;
  372.     else if (new->y > desk.y+desk.h-2*sys_hchar)
  373.         new->y = desk.y+desk.h-2*sys_hchar;
  374.     if (new->x <= 0)
  375.         new->x = -1;
  376.     else if (new->x > desk.x+desk.w-3*sys_wchar)
  377.         new->x = desk.x+desk.w-3*sys_wchar;
  378. }
  379.  
  380. LOCAL VOID get_work (WINDP window, RECT *new, WORD mode)
  381. {
  382.     if (mode & WORK_SIZED)
  383.     {
  384.         if (new->w < MIN_WIDTH)
  385.             new->w = MIN_WIDTH;
  386.         else if (new->w > desk.w)
  387.             new->w = desk.w;
  388.         if (new->h < MIN_HEIGHT)
  389.             new->h = MIN_HEIGHT;
  390.         else if (new->h > desk.h)
  391.             new->h = desk.h;
  392.     }
  393.  
  394.     wind_calc (WC_WORK, window->kind,                /* Innenbereich berechnen */
  395.                   new->x, new->y, new->w, new->h,
  396.                   &new->x, &new->y, &new->w, &new->h);
  397.     snap_window (window, new, mode);
  398.  
  399.     /* work und w_* (und doc) anpassen */
  400.     window->work.x = new->x;
  401.     window->work.y = new->y;
  402.     if (mode & WORK_SIZED)
  403.     {
  404.         long max_doc;
  405.  
  406.         window->work.w = new->w;
  407.         window->w_width  = window->work.w / window->xfac;
  408.         max_doc = window->doc.w - window->w_width;
  409.         if (max_doc < 0)
  410.             max_doc = 0;
  411.         if (window->doc.x > max_doc)                /* Jenseits rechter Bereich */
  412.             window->doc.x = max_doc;
  413.  
  414.         window->work.h = new->h;
  415.         window->w_hight  = window->work.h/window->yfac;
  416.         max_doc = window->doc.h - window->w_hight;
  417.         if (max_doc < 0)
  418.             max_doc = 0;
  419.         if (window->doc.y > max_doc)                /* Jenseits unterer Bereich */
  420.             window->doc.y = max_doc;
  421.     }
  422.  
  423.     if (window->opened)
  424.     {
  425.         wind_calc (WC_BORDER, window->kind,        /* Rand berechnen */
  426.                       new->x, new->y, new->w, new->h,
  427.                       &new->x, &new->y, &new->w, &new->h);
  428.         wind_set (window->handle, WF_CURRXYWH, new->x, new->y, new->w, new->h);
  429.     }
  430.  
  431.     if (mode&WORK_SIZED)
  432.         set_sliders (window, HORIZONTAL+VERTICAL, SLPOS+SLSIZE);
  433. } /* get_work */
  434.  
  435. /***************************************************************************/
  436. /* Kreiere Fenster                                                                            */
  437. /***************************************************************************/
  438.  
  439. WINDP create_window (WORD kind, WORD class, WORD link, VOID (*crt)(WORD link, WINDP window))
  440. {
  441.     WINDP window, w;
  442.     WORD    i, *ptr, h_age, h_x, h_y;
  443.     RECT    help;
  444.  
  445.     if (free_list==NULL)                            /* kein Platz mehr für Fenster */
  446.     {
  447.         free_list = (WINDP)Malloc(sizeof(WINDOW));
  448.         if (free_list==NULL)
  449.         {
  450.             note(1, NOWINDOW);
  451.             return (NULL);
  452.         }
  453.         else
  454.         {
  455.             ptr = (WORD*)free_list;
  456.             for (i = (short)sizeof(WINDOW) / 2; (--i)>=0; )
  457.                 *ptr++ = 0;
  458.         }
  459.     }
  460.     /* Unbenutzt und gleiche Klasse und groeszter init */
  461.     i = -1;
  462.     w = NULL;
  463.     for (window=free_list; window!=NULL; window=window->next)
  464.     {
  465.         if (window->class==class && window->init>i)
  466.         {
  467.             i = window->init;
  468.             w = window;
  469.         }
  470.     }
  471.     window = w;
  472.     if (window==NULL)
  473.     {
  474.         /* Unbenutzt und gleiche Klasse */
  475.         for (window=free_list; window!=NULL; window=window->next)
  476.         {
  477.             if (window->class==class)
  478.                 break;
  479.         }
  480.         /* Unbenutzt und nicht gleiche Klasse */
  481.         if (window==NULL)
  482.         {
  483.             for (window=free_list; window!=NULL; window=window->next)
  484.             {
  485.                 if (window->work.w==0)
  486.                     break;
  487.             }
  488.             if (window==NULL)                                /* Nur unbenutzt */
  489.             {
  490.                 window = free_list;
  491.                 window->work.h = window->work.w = 0;
  492.             }
  493.         }
  494.     }
  495.  
  496.     if (free_list==window)                            /* Aushängen */
  497.         free_list = window->next;
  498.     else
  499.     {
  500.         for (w=free_list; w->next!=window; w=w->next) ;
  501.         w->next = window->next;
  502.     }
  503.  
  504.     help = window->work;                                /* Löschen */
  505.     h_age = window->age;
  506.     h_x = window->icon_x;
  507.     h_y = window->icon_y;
  508. #if sizeof(WINDOW)&1
  509.     So gehts nicht
  510. #endif
  511.     ptr = (WORD*)window;
  512.     for (i= (short) sizeof(WINDOW) / 2; (--i)>=0; )
  513.         *ptr++ = 0;
  514.  
  515.     if (used_list==NULL)                                /* Einhängen */
  516.         used_list = window;
  517.     else
  518.     {
  519.         for (w=used_list; w->next!=NULL; w=w->next) ;
  520.         w->next = window;
  521.     }
  522.  
  523.     window->age            = h_age;
  524.     window->handle        = NO_HANDLE;
  525.     window->kind        = kind;
  526.     window->class        = class;
  527.     window->link         = link;
  528.     (* crt)(link, window);
  529.     if (class != CLASS_ICON)
  530.     {
  531.         if (help.w == 0 || help.h == 0)
  532.             help = window->work;
  533.         size_window(window, &help, FALSE);
  534.         if (is_icon_on_desk(window->link))
  535.         {
  536.             if (h_x || h_y)
  537.             {
  538.                 move_icon_to(window->link,h_x,h_y);
  539.                 show_icon(window->link);
  540.             }
  541.             else
  542.             {
  543.                 show_icon(window->link);
  544.                 get_icon_pos(window->link,&window->icon_x,&window->icon_y);
  545.             }
  546.         }
  547.     }
  548.     return (window);
  549. } /* create_window */
  550.  
  551. /***************************************************************************/
  552. /* Öffne Fenster                                                                                */
  553. /***************************************************************************/
  554.  
  555.  
  556. BOOLEAN open_window (WINDP window)
  557. {
  558.     WORD    wh;
  559.  
  560.     clr_undo();
  561.     if (!window->opened)        /* Erstes Öffnen */
  562.     {
  563.         if (window->class == DESK)
  564.             wh = DESK;
  565.         else
  566.         {
  567.             wh = wind_create (window->kind, desk.x, desk.y, desk.w, desk.h);
  568.             if (wh < 0)
  569.                 return FALSE;                                            /* Kein Fenster mehr */
  570.         }
  571.         window->handle = wh;
  572.     }
  573.     else
  574.         wh = window->handle;
  575.  
  576.     unclick_window();
  577.     window->opened++;                                    /* Fenster einmal mehr offen */
  578.     window->flags &= ~WI_FULLED;                    /* Fenster hat nicht volle Größe */
  579.  
  580.     if (wh == DESK)                                        /* GEM Desktop */
  581.     {
  582.         if (!no_desktop)
  583.         {
  584.             wind_set(DESK, WF_NEWDESK, desktop, 0);
  585.             form_dial(FMD_FINISH, 0, 0, 0, 0, desk.x, desk.y, desk.w, desk.h);
  586.         }
  587.     }
  588.     else
  589.     {
  590.         RECT    r;
  591.  
  592.         wind_calc (WC_BORDER, window->kind,        /* Rand berechnen */
  593.                       window->work.x, window->work.y, window->work.w, window->work.h,
  594.                       &r.x, &r.y, &r.w, &r.h);
  595.         if (window->kind&NAME)                        /* Name setzen */
  596.             wind_set (wh, WF_NAME, window->titel);
  597.         if (window->kind&INFO)                        /* Infozeile setzen */
  598.             wind_set (wh, WF_INFO, window->info);
  599.         window->slider_pos = -1;                    /* garantiert setzen */
  600.         set_sliders (window, HORIZONTAL+VERTICAL, SLPOS+SLSIZE);
  601.  
  602.         if (window->opened==1)                        /* erstes Öffnen */
  603.         {
  604.             wind_open (wh, r.x, r.y, r.w, r.h);    /* Fenster öffnen */
  605.             top_handle = wh;
  606.             while (idle())
  607.                 ;
  608.         }
  609.     }
  610.     if (window->opened == 1)
  611.     {
  612.         move_to_top (window);                        /* Neu geöffnetes Fenster oben */
  613.         if (wh != DESK)
  614.         {
  615.             redraw_window(window, &window->work);
  616.             window->flags |= WI_NOTDRAWED;
  617.         }
  618.     }
  619.     if (wh != DESK)
  620.         send_avwinopen(wh);
  621.     return TRUE;
  622. } /* open_window */
  623.  
  624. /***************************************************************************/
  625. /* Schließe Fenster                                                                            */
  626. /***************************************************************************/
  627.  
  628. VOID close_window (WINDP window)
  629. {
  630.     WORD    wh;
  631.  
  632.     wh    = window->handle;
  633.     unclick_window ();            /* Deselektieren */
  634.  
  635.     if (window->opened)            /* Fenster offen? */
  636.     {
  637.         Wake_mouse();                /* Muß an sein */
  638.         if (wh==DESK)                /* GEM Desktop */
  639.         {
  640.             if (!no_desktop)
  641.             {
  642.                 wind_set(DESK, WF_NEWDESK, NULL);/* Original Desktop */
  643.                 form_dial (FMD_FINISH, 0, 0, 0, 0, desk.x, desk.y, desk.w, desk.h);
  644.             }
  645.         }
  646.         else if (window->opened == 1)
  647.         {
  648.             if (window->close != NULL)
  649.                 (*window->close) (window);
  650.  
  651.             wind_close (wh);        /* Schließe Fenster */
  652.             wind_delete (wh);        /* Window-Handle freigeben */
  653.  
  654.             if (wh != DESK)
  655.                 send_avwinclose(wh);
  656.  
  657.             get_realtop();
  658.             idle();
  659.         }
  660.         window->opened--;            /* Fenster einmal geschlossen */
  661.         if (!window->opened)            /* Fenster ganz schließen */
  662.         {
  663.             window->handle    = NO_HANDLE;    /* Kein Handle mehr verfügbar */
  664.             move_to_end (window);
  665.             clr_undo();
  666.         }
  667.     }
  668. } /* close_window */
  669.  
  670. /***************************************************************************/
  671.  
  672. VOID destruct_window(WINDP window)
  673. {
  674.     WINDP w;
  675.  
  676.     if (window->flags & WI_ICONIFIED)
  677.         window->opened = 1;
  678.  
  679.     while(window->opened)
  680.         close_window (window);                        /* Schließe Fenster */
  681.  
  682.     if (used_list==window)                            /* Aushängen */
  683.         used_list = window->next;
  684.     else
  685.     {
  686.         for (w = used_list; w->next!=window; w=w->next) ;
  687.         w->next = window->next;
  688.     }
  689.     if (window>=windrec && window<&windrec[MAX_WINDOW])
  690.     {
  691.         if (free_list==NULL || free_list->age>window->age)
  692.         {
  693.             window->next = free_list;
  694.             free_list = window;
  695.         }
  696.         else
  697.         {
  698.             for (w=free_list; (w->next!=NULL) && (w->next->age<window->age); w=w->next) ;
  699.             window->next = w->next;
  700.             w->next = window;
  701.         }
  702.     }
  703.     else
  704.     {
  705.         Mfree(window);
  706.     }
  707. }
  708.  
  709. /***************************************************************************/
  710. /* Suche und zeichne überlagernde Rechtecke von Fenstern                            */
  711. /***************************************************************************/
  712.  
  713. VOID redraw_window (WINDP window, CONST RECT *area)
  714. {
  715.     WORD    wh;
  716.     RECT    r1;
  717.  
  718.     if (window==NULL)
  719.         return;
  720.     if (window->flags & WI_NOTDRAWED)
  721.     {
  722.         window->flags &= (~WI_NOTDRAWED);
  723.     }
  724.     else if (window->opened || (window->flags & WI_ICONIFIED) )
  725.     {
  726.         if (window->flags & WI_ICONIFIED)
  727.         {
  728.             /* Icon-Position wieder eintragen, da alle Fenster den gleichen
  729.              * Objektbaum benutzen!!!
  730.              */
  731.             window->icon[0].ob_x = window->ix;
  732.             window->icon[0].ob_y = window->iy;
  733.         }
  734.         wh = window->handle;
  735.         if (rc_first (wh, area, &r1))
  736.         {
  737.             Hide_mouse ();
  738.             do
  739.             {
  740.                 if (window->flags & WI_ICONIFIED)
  741.                 {
  742.                     if (myrc_intersect (area, &r1))
  743.                         objc_draw (window->icon, ROOT, MAX_DEPTH, r1.x, r1.y, r1.w, r1.h);
  744.                 }
  745.                 else if (window->opened)
  746.                 {
  747.                     if (window->draw!=NULL)                /* Zeichenroutine ausführen */
  748.                         (*window->draw) (window, &r1);
  749.                 }
  750.             }
  751.             while(rc_next(wh,&r1));
  752.             Show_mouse ();
  753.         }
  754.     }
  755. } /* redraw_window */
  756.  
  757. /***************************************************************************/
  758. /* Bringt anderes Fenster nach oben                                                        */
  759. /***************************************************************************/
  760.  
  761. VOID cycle_window(VOID)
  762. {
  763.     WINDP    window, w;
  764.  
  765.     window = NULL;
  766.     for (w=used_list; w!=NULL; w=w->next)
  767.     {
  768.         if (w->opened && w->class != DESK && w->class != CLASS_PROJEKT)
  769.             window = w;
  770.     }
  771.     top_window(window);
  772. }
  773.  
  774. /***************************************************************************/
  775. /* Räume alle offenen Fenster auf                                                        */
  776. /***************************************************************************/
  777.  
  778. VOID clearup_windows(WORD mode, WORD w, WORD h)
  779. {
  780.     WINDP    winds[MAX_WINDOW], window;
  781.     RECT    r1, r2;
  782.     WORD    i, anz;
  783.  
  784.     for (window=used_list,anz=0; window!=NULL; window=window->next)
  785.     {
  786.         if (window->opened && window->kind&SIZER && window->flags&WI_TEXT)
  787.             winds[anz++] = window;
  788.     }
  789.     if (anz==0) return;
  790.     if (mode==0)
  791.     {
  792.         r1.x = desk.x+sys_wchar;
  793.         r1.y = desk.y+(sys_hchar>>1);
  794.         r1.w = desk.w-anz*sys_wchar;
  795.         r1.h = desk.h-anz*sys_hchar;
  796.         if (w>0 || h>0)
  797.         {
  798.             wind_calc(WC_WORK, winds[0]->kind, r1.x, r1.y, r1.w, r1.h,
  799.  
  800.                                                             &r1.x, &r1.y, &r1.w, &r1.h);
  801.             if (w>0) r1.w = w*gl_wchar;
  802.             if (h>0) r1.h = h*gl_hchar;
  803.             wind_calc(WC_BORDER, winds[0]->kind, r1.x, r1.y, r1.w, r1.h,
  804.                                                                 &r1.x, &r1.y, &r1.w, &r1.h);
  805.         }
  806.         while ((--anz)>=0)
  807.         {
  808.             size_window(winds[anz], &r1, TRUE);
  809.             r1.x += sys_wchar;
  810.             r1.y += sys_hchar;
  811.         }
  812.         return;
  813.     }
  814.     else if (mode==1)        /* nebeneinander */
  815.     {
  816.         i = (anz+1)>>1;
  817.         r1.x = desk.x+sys_wchar;
  818.         r1.y = desk.y+(sys_hchar>>1);
  819.         r1.w = (desk.w>>1)-i*sys_wchar;
  820.         r1.h = desk.h-i*sys_hchar;
  821.         r2 = r1;
  822.         r2.x += (desk.w>>1);
  823.     }
  824.     else                        /* untereinander */
  825.     {
  826.         i = (anz+1)>>1;
  827.         r1.x = desk.x+sys_wchar;
  828.         r1.y = desk.y+(sys_hchar>>1);
  829.         r1.w = desk.w-i*sys_wchar;
  830.         r1.h = (desk.h>>1)-i*sys_hchar;
  831.         r2 = r1;
  832.         r2.y += (desk.h>>1);
  833.     }
  834.     while ((--anz)>=0)
  835.     {
  836.         size_window(winds[anz], (anz&1)?&r2:&r1, TRUE);
  837.         if (anz&1)
  838.         {
  839.             r2.x += sys_wchar;
  840.             r2.y += sys_hchar;
  841.         }
  842.         else
  843.         {
  844.             r1.x += sys_wchar;
  845.             r1.y += sys_hchar;
  846.         }
  847.     }
  848. }
  849.  
  850. LOCAL VOID top_qed(VOID)
  851. {
  852.     /*
  853.      * Unter MagiC kann es passieren, daß oberstes Fenster und Menüzeile
  854.      * nicht zur selben APP gehören!
  855.      */
  856.     if (magx)
  857.     {
  858.         WORD    id;
  859.  
  860. /*        wind_update(BEG_UPDATE);*/
  861.         id = menu_bar(NULL, -1);
  862. /*        wind_update(END_UPDATE);*/
  863.         if (id != gl_apid)
  864.             send_m_special(SMC_SWITCH, gl_apid);
  865.     }
  866. }
  867.  
  868. /***************************************************************************/
  869. /* Fenster wurde durch andere getopped/geuntopped                                     */
  870. /***************************************************************************/
  871. VOID ontop_window(WINDP window)
  872. {
  873.     top_qed();
  874.     if (window != NULL && window->ontop != NULL)
  875.         (*window->ontop)(window);
  876. }
  877.  
  878. VOID untop_window(WINDP window)
  879. {
  880.     if (window != NULL && window->untop != NULL)
  881.         (*window->untop)(window);
  882. }
  883.  
  884. /***************************************************************************/
  885. /* Bringe Fenster nach oben                                                                */
  886. /***************************************************************************/
  887.  
  888. VOID top_window (WINDP window)
  889. {
  890.     WORD    wh;
  891.  
  892.     top_qed();
  893.     if (window == NULL || (!window->opened) && !(window->flags & WI_ICONIFIED))
  894.         return;
  895.     if (window->class == DESK)
  896.         return;        /* Desktop im HP */
  897.     if (window->top != NULL)
  898.         (*window->top)(window);
  899.     wh = window->handle;
  900.     wind_set (wh, WF_TOP);
  901.     top_handle = wh;
  902.     if (window != sel_window)
  903.         unclick_window();
  904.     if (window != used_list)                /* War noch nicht top */
  905.     {
  906.         clr_undo();
  907.         move_to_top (window);            /* Neues Fenster oben im Keller */
  908.     }
  909. } /* top_window */
  910.  
  911. /************************************************************************/
  912. /* Bringe Fenster nach hinten                                                            */
  913. /************************************************************************/
  914.  
  915. VOID bottom_window (WINDP window, WORD which)
  916. {
  917.     WORD    wh;
  918.  
  919.     if (window == NULL || (!window->opened) && !(window->flags & WI_ICONIFIED))
  920.         return;
  921.     if (window->class == DESK)
  922.         return;
  923.     wh = window->handle;
  924.     if (window->bottom != NULL)
  925.         (*window->bottom)(window);
  926.     if (which == WM_BOTTOMED)
  927.         wind_set (wh, WF_BOTTOM);            /* MTOS, MagiC >= 3 */
  928.     else
  929.         wind_set(wh, WF_M_BACKDROP);        /* Magic 2 */
  930.     if (window != used_list)
  931.     {
  932.         clr_undo();
  933.         move_to_end(window);
  934.     }
  935.     get_realtop();            /* qed über das neue top-Fenster informieren */
  936.     memset(msgbuff, 0, (WORD) sizeof(msgbuff));
  937.     msgbuff[0] = WM_TOPPED;
  938.     msgbuff[3] = top_handle;
  939.     send_msg(gl_apid);
  940. } /* bottom_window */
  941.  
  942. /***************************************************************************/
  943. /* Scrolle den Fensterinhalt                                                                */
  944. /***************************************************************************/
  945.  
  946. LOCAL VOID scroll_window (WINDP window, WORD dir, long delta)
  947. {
  948.     MFDB    s, d;
  949.     WORD    xy[8];
  950.     RECT    r;
  951.     BOOLEAN    draw;
  952.  
  953.     draw = FALSE;
  954.     wind_get (window->handle, WF_FIRSTXYWH, &r.x, &r.y, &r.w, &r.h);
  955.     if (r.w != window->work.w || r.h != window->work.h)
  956.         draw = TRUE;
  957.  
  958.     r = window->work;                            /* Hole workbereich */
  959.     if (!myrc_intersect(&desk,&r))
  960.         return;
  961.  
  962.     if (dir&HORIZONTAL)
  963.     {
  964.         delta *= window->xfac;
  965.         if (labs(delta) >= r.w)
  966.             draw = TRUE;
  967.     }
  968.     else
  969.     {
  970.         delta *= window->yfac;
  971.         if (labs(delta) >= r.h)
  972.             draw = TRUE;
  973.     }
  974.  
  975.     if (!draw)
  976.     {
  977.         rect2array (&r, xy);                        /* Quelle für vro_cpyfm */
  978.         xy[4] = xy[0];                                /* Ziel für vro_cpyfm */
  979.         xy[5] = xy[1];
  980.         xy[6] = xy[2];
  981.         xy[7] = xy[3];
  982.  
  983.         if (dir&HORIZONTAL)                        /* Horizontales Scrolling */
  984.         {
  985.             if (delta > 0)                            /* Links Scrolling */
  986.             {
  987.                 xy[0] += (short) delta;            /* Werte für vro_cpyfm */
  988.                 xy[6] -= (short) delta;
  989.  
  990.                 r.x += r.w - (short)delta;        /* Rechter Bereich nicht gescrollt, */
  991.                 r.w  = (short)delta;                /* muß neu gezeichnet werden */
  992.             }
  993.             else                                        /* Rechts Scrolling */
  994.             {
  995.                 xy[2] += (short)delta;            /* Werte für vro_cpyfm */
  996.                 xy[4] -= (short)delta;
  997.  
  998.                 r.w = (short)(-delta);            /* Linken Bereich noch neu zeichnen */
  999.             }
  1000.         }
  1001.         else                                            /* Vertikales Scrolling */
  1002.         {
  1003.             if (delta > 0)                            /* Aufwärts Scrolling */
  1004.             {
  1005.                 xy[1] += (short)delta;                    /* Werte für vro_cpyfm */
  1006.                 xy[7] -= (short)delta;
  1007.  
  1008.                 r.y += r.h - (short)delta;                    /* Unterer Bereich nicht gescrollt, */
  1009.                 r.h  = (short) delta;                        /* muß neu gezeichnet werden */
  1010.             }
  1011.             else                                        /* Abwärts Scrolling */
  1012.             {
  1013.                 xy[3] += (short)delta;                    /* Werte für vro_cpyfm */
  1014.                 xy[5] -= (short)delta;
  1015.  
  1016.                 r.h = (short)(-delta);                    /* Oberen Bereich noch neu zeichnen */
  1017.             }
  1018.         }
  1019.         s.fd_addr = d.fd_addr = NULL;            /* Erzwinge Bildschirmadresse */
  1020.         set_clip(FALSE,NULL);
  1021.         Hide_mouse ();
  1022.         vro_cpyfm (vdi_handle, S_ONLY, xy, &s, &d);
  1023.         Show_mouse ();
  1024.         redraw_window (window, &r);
  1025.     }
  1026.     else
  1027.         redraw_window (window, &r);            /* Fenster zeichnen */
  1028. } /* scroll_window */
  1029.  
  1030. /***************************************************************************/
  1031. /* Reagiere auf Anklicken eines Pfeils                                                    */
  1032. /***************************************************************************/
  1033.  
  1034. LOCAL VOID do_arrow(WINDP window, WORD dir, long delta)
  1035. {
  1036.     if (delta)
  1037.     {
  1038.         if (dir==HORIZONTAL)                                     /* Horizontale Pfeile und Schieber */
  1039.             window->doc.x += delta;                            /* Neue Position */
  1040.         else                                                        /* Vertikale Pfeile und Schieber */
  1041.             window->doc.y += delta;                            /* Neue Position */
  1042.         if (window->opened)
  1043.         {
  1044.             set_sliders (window, dir, SLPOS);            /* Schieber setzen */
  1045.             scroll_window (window, dir, delta);
  1046.         }
  1047.     }
  1048. }
  1049.  
  1050. VOID arrow_window (WINDP window, WORD arrow, long amount)
  1051. {
  1052.     WORD w, h, dir;
  1053.     long oldpos, newpos, max_slide;
  1054.  
  1055.     if (window!=NULL)
  1056.     {
  1057.         w      = window->w_width;                             /* Breite in Zeichen */
  1058.         h      = window->w_hight;                             /* Höhe in Zeichen */
  1059.  
  1060.         if (arrow <= WA_DNLINE)
  1061.         {
  1062.             oldpos = newpos = window->doc.y;
  1063.             dir     = VERTICAL;
  1064.             max_slide = window->doc.h - h;                /* Maximale Position */
  1065.         }
  1066.         else
  1067.         {
  1068.             oldpos = newpos = window->doc.x;
  1069.             dir     = HORIZONTAL;
  1070.             max_slide = window->doc.w - w;                /* Maximale Position */
  1071.         }
  1072.         switch (arrow)
  1073.         {
  1074.             case WA_UPPAGE : newpos -= h * amount; break;
  1075.             case WA_DNPAGE : newpos += h * amount; break;
  1076.             case WA_UPLINE : newpos -= amount;        break;
  1077.             case WA_DNLINE : newpos += amount;        break;
  1078.             case WA_LFPAGE : newpos -= w * amount; break;
  1079.             case WA_RTPAGE : newpos += w * amount; break;
  1080.             case WA_LFLINE : newpos -= amount;        break;
  1081.             case WA_RTLINE : newpos += amount;        break;
  1082.         }
  1083.  
  1084.         if (newpos > max_slide) newpos = max_slide;    /* Jenseits des Randes */
  1085.         if (newpos < 0) newpos = 0;                         /* Jenseits des Randes */
  1086.         do_arrow(window, dir, newpos-oldpos);
  1087.     }
  1088. } /* arrow_window */
  1089.  
  1090. /***************************************************************************/
  1091. /* Reagiere auf Bewegen der Schieber                                                    */
  1092. /***************************************************************************/
  1093.  
  1094. VOID h_slider (WINDP window, WORD new_value)
  1095. {
  1096.     WORD w;
  1097.     long oldpos, newpos, max_slide;
  1098.  
  1099.     if (window != NULL)
  1100.     {
  1101.         w                = window->w_width;                    /* Breite in Zeichen */
  1102.         max_slide    = window->doc.w - w;                    /* Maximale Position */
  1103.         oldpos        = window->doc.x;
  1104.         newpos        = (long)new_value * max_slide;
  1105.         newpos        = (newpos+500) / 1000;                /* Teilen + Runden */
  1106.  
  1107.         if (newpos > max_slide) newpos = max_slide;    /* Jenseits des Randes */
  1108.         if (newpos < 0) newpos = 0;                        /* Jenseits des Randes */
  1109.         do_arrow(window, HORIZONTAL, newpos-oldpos);
  1110.     }
  1111. } /* h_slider */
  1112.  
  1113. /*****************************************************************************/
  1114.  
  1115. VOID v_slider (WINDP window, WORD new_value)
  1116. {
  1117.     WORD h;
  1118.     long oldpos, newpos, max_slide;
  1119.  
  1120.     if (window != NULL)
  1121.     {
  1122.         h                = window->w_hight;                    /* Höhe in Zeichen */
  1123.         max_slide    = window->doc.h - h;                    /* Maximale Position */
  1124.         oldpos        = window->doc.y;
  1125.         newpos        = (long)new_value * max_slide;
  1126.         newpos        = (newpos+500) / 1000;                /* Teilen + Runden */
  1127.  
  1128.         if (newpos > max_slide) newpos = max_slide;    /* Jenseits des Randes */
  1129.         if (newpos < 0) newpos = 0;                        /* Jenseits des Randes */
  1130.         do_arrow(window, VERTICAL, newpos-oldpos);
  1131.     }
  1132. } /* v_slider */
  1133.  
  1134. /***************************************************************************/
  1135. /* Setze Schieberpositionen und Schiebergröße                                        */
  1136. /***************************************************************************/
  1137.  
  1138. VOID set_sliders (WINDP window, WORD which, WORD mode)
  1139. {
  1140.     WORD    wh;
  1141.     WORD    size, newval, oldval;
  1142.     long    max_doc;
  1143.  
  1144.     if (window->opened)
  1145.     {
  1146.         wh = window->handle;
  1147.  
  1148.         if ((which&HORIZONTAL) && (window->kind&HSLIDE))
  1149.         {
  1150.             size        = window->w_width;
  1151.             max_doc    = window->doc.w-size;
  1152.  
  1153.             if (mode&SLPOS)
  1154.             {
  1155.                 if (max_doc<=0)            /* Fenster zu groß oder passend */
  1156.                     newval = 0;
  1157.                 else
  1158.                     newval = (short)((1000L * window->doc.x) / max_doc);
  1159.  
  1160.                 wind_get (wh, WF_HSLIDE, &oldval);
  1161.                 if (newval!=oldval)
  1162.                     wind_set (wh, WF_HSLIDE, newval);
  1163.             }
  1164.             if (mode&SLSIZE)
  1165.             {
  1166.                 if (window->doc.w<=0)        /* Fenster zu groß oder passend */
  1167.                     newval = 1000;
  1168.                 else
  1169.                     newval = (short)((1000L * size) / window->doc.w);
  1170.                 wind_get (wh, WF_HSLSIZE, &oldval);
  1171.                 if (newval!=oldval)
  1172.                     wind_set (wh, WF_HSLSIZE, newval);
  1173.             }
  1174.         }
  1175.         if ((which&VERTICAL) && (window->kind&VSLIDE))
  1176.         {
  1177.             size      = window->w_hight;
  1178.             max_doc = window->doc.h-size;
  1179.  
  1180.             if (mode&SLPOS)
  1181.             {
  1182.                 if (max_doc<=0)            /* Fenster zu groß oder passend */
  1183.                     newval = 0;
  1184.                 else
  1185.                     newval = (short)((1000L*window->doc.y) / max_doc);
  1186.                 if (newval!=window->slider_pos)
  1187.                 {
  1188.                     wind_set (wh, WF_VSLIDE, newval);
  1189.                     window->slider_pos = newval;
  1190.                 }
  1191.             }
  1192.             if (mode&SLSIZE)
  1193.             {
  1194.                 if (window->doc.h <= 1)        /* Fenster zu groß oder passend */
  1195.                     newval = 1000;
  1196.                 else
  1197.                     newval = (short)((1000L*size) / window->doc.h);
  1198.                 wind_get (wh, WF_VSLSIZE, &oldval);
  1199.                 if (newval!=oldval)
  1200.                     wind_set (wh, WF_VSLSIZE, newval);
  1201.             }
  1202.         }
  1203.     }
  1204. } /* set_sliders */
  1205.  
  1206. /***************************************************************************/
  1207. /* Setze Fenstername                                                                       */
  1208. /***************************************************************************/
  1209.  
  1210. VOID set_wname(WINDP window, CONST UBYTE *name)
  1211. {
  1212.     UBYTE    str[WINSTRLEN];
  1213.  
  1214.     strcpy(window->name, name);
  1215.     strcpy(str, " ");
  1216.     if (window->changed)
  1217.     {
  1218.         strcat(str, "*");
  1219.         strncat(str, name, WINSTRLEN - 3);
  1220.     }
  1221.     else
  1222.         strncat(str, name, WINSTRLEN - 2);
  1223.     strcat(str, " ");
  1224.     strcpy(window->titel, str);
  1225.     if (window->opened && window->kind & NAME)
  1226.         wind_set(window->handle, WF_NAME, window->titel);
  1227. }
  1228.  
  1229. /***************************************************************************/
  1230. /* Setze Fensterinfo                                                                       */
  1231. /***************************************************************************/
  1232.  
  1233. VOID set_winfo(WINDP window, CONST UBYTE *info)
  1234. {
  1235.     strcpy(window->info, info);
  1236.     if (window->opened && window->kind & INFO)
  1237.         wind_set(window->handle, WF_INFO, window->info);
  1238. }
  1239.  
  1240. /***************************************************************************/
  1241. /* '*' vor Fenstertitel                                                                        */
  1242. /***************************************************************************/
  1243.  
  1244. VOID change_window (WINDP window, BOOLEAN changed)
  1245. {
  1246.     if (window->changed!=changed)
  1247.     {
  1248.         window->changed = changed;
  1249.         set_wname(window,window->name);
  1250.     }
  1251. }
  1252.  
  1253. /***************************************************************************/
  1254. /* Vergößere Fenster auf volle Größe bzw. verkleinere Fenster                    */
  1255. /***************************************************************************/
  1256.  
  1257. VOID full_window (WINDP window)
  1258. {
  1259.     RECT    new;
  1260.  
  1261.     if (window!=NULL && window->kind&FULLER)
  1262.     {
  1263.         if (window->flags&WI_FULLED)                /* Mache Fenster klein */
  1264.             wind_get (window->handle, WF_PREVXYWH, &new.x, &new.y, &new.w, &new.h);
  1265.         else                                                /* Mache Fenster groß */
  1266.             wind_get (window->handle, WF_FULLXYWH, &new.x, &new.y, &new.w, &new.h);
  1267.         test_work (&new);
  1268.         get_work (window, &new, WORK_MOVED|WORK_SIZED);
  1269.         window->flags ^= WI_FULLED;
  1270.     }
  1271. } /* full_window */
  1272.  
  1273. /***************************************************************************/
  1274. /* Ändere Fenstergröße                                                                        */
  1275. /***************************************************************************/
  1276.  
  1277. VOID size_window (WINDP window, CONST RECT *new, BOOLEAN border)
  1278. {
  1279.     RECT r;
  1280.  
  1281.     if (window!=NULL)
  1282.     {
  1283.         r = *new;
  1284.         if (!border)
  1285.             wind_calc (WC_BORDER, window->kind,        /* Rand berechnen */
  1286.                           r.x, r.y, r.w, r.h, &r.x, &r.y, &r.w, &r.h);
  1287.         if (window->kind&SIZER)
  1288.         {
  1289.             test_work (&r);
  1290.             get_work (window, &r, WORK_SIZED);
  1291.             window->flags &= ~WI_FULLED;
  1292.             if (window->flags&WI_REDRAW)
  1293.                 redraw_window(window,&window->work);
  1294.         }
  1295.         else
  1296.             move_window(window,&r);
  1297.     }
  1298. } /* size_window */
  1299.  
  1300. /***************************************************************************/
  1301. /* Bewege Fenster                                                                                */
  1302. /***************************************************************************/
  1303.  
  1304. VOID move_window (WINDP window, CONST RECT *new)
  1305. {
  1306.  
  1307.     if (window != NULL)
  1308.     {
  1309.         if (window->flags & WI_ICONIFIED)
  1310.         {
  1311.             WORD    x, y, d;
  1312.  
  1313.             wind_set(window->handle, WF_CURRXYWH, new->x, new->y, new->w, new->h);
  1314.             wind_get(window->handle, WF_WORKXYWH, &x, &y, &d, &d);
  1315.             window->icon[0].ob_x = x;
  1316.             window->icon[0].ob_y = y;
  1317.             window->ix = window->icon[0].ob_x;
  1318.             window->iy = window->icon[0].ob_y;
  1319.         }
  1320.         else if (window->kind & MOVER)
  1321.         {
  1322.             RECT r;
  1323.  
  1324.             r = *new;
  1325.             /* test_work (&r); hier nicht wg. MagiX */
  1326.             get_work (window, &r, WORK_MOVED);
  1327.             window->flags &= ~WI_FULLED;
  1328.         }
  1329.     }
  1330. } /* move_window */
  1331.  
  1332. /***************************************************************************/
  1333. /* Iconify                                                                                        */
  1334. /***************************************************************************/
  1335.  
  1336. VOID iconify_window(WINDP window, CONST RECT *new, BOOLEAN flag)
  1337. {
  1338.  
  1339.     unclick_window ();            /* Deselektieren */
  1340.  
  1341.     if (window->opened && !(window->flags & WI_ICONIFIED))
  1342.     {
  1343.         WORD    x, y, w, h;
  1344.  
  1345.  
  1346.         if (window->iconify != NULL)
  1347.             (*window->iconify) (window);
  1348.  
  1349.         /* alte Größe merken */
  1350.         wind_get(window->handle, WF_CURRXYWH, &window->old_size.x, &window->old_size.y,
  1351.                                                           &window->old_size.w, &window->old_size.h);
  1352.  
  1353.         wind_set(window->handle, WF_ICONIFY, new->x, new->y, new->w, new->h);
  1354.  
  1355.         if (flag)                /* alliconify: Fenster erst noch öffnen! */
  1356.             wind_open(window->handle, new->x, new->y, new->w, new->h);
  1357.  
  1358.         wind_get(window->handle, WF_WORKXYWH, &x, &y, &w, &h);
  1359.         window->icon[0].ob_x = x;
  1360.         window->icon[0].ob_y = y;
  1361.         window->icon[0].ob_width = w;
  1362.         window->icon[0].ob_height = h;
  1363.         window->icon[1].ob_x = (w - window->icon[1].ob_width) / 2;
  1364.         window->icon[1].ob_y = (h - window->icon[1].ob_height) / 2;
  1365.         window->ix = window->icon[0].ob_x;
  1366.         window->iy = window->icon[0].ob_y;
  1367.  
  1368.         window->flags |= WI_ICONIFIED;
  1369.         if (window->class == CLASS_EDIT)
  1370.             window->flags &= ~WI_MOUSE;
  1371.         window->opened = 0;
  1372.         bottom_window(window, WM_BOTTOMED);
  1373.     }
  1374. }
  1375.  
  1376.  
  1377. LOCAL VOID    crt_wicon(WORD icon, WINDP window)
  1378. {
  1379.     window->opened = 1;        /* wir gaukeln iconify_window ein geöffnetes Fenster
  1380.                                      * vor, damit der Iconify klappt.
  1381.                                      */
  1382.     window->icon = winicon;
  1383. }
  1384.  
  1385.  
  1386. VOID    alliconify(CONST RECT *new)
  1387. {
  1388.     WORD    i, anz;
  1389.     WORD    ic, icp[MAX_ICON_ANZ];
  1390.     WINDP    window;
  1391.  
  1392.  
  1393.     if (makro_rec)
  1394.     {
  1395.         mybeep();
  1396.         return;
  1397.     }
  1398.  
  1399.     /* Zunächst alle Fenster schließen und in Liste merken */
  1400.     i = all_icons(icp);
  1401.     anz = 0;
  1402.     while ((--i) >= 0)
  1403.     {
  1404.         ic = icp[i];
  1405.         if (ic != 0)
  1406.         {
  1407.             window = get_window(ic);
  1408.             if (window != NULL)
  1409.                 if (window->handle != NO_HANDLE && ((window->opened) || (window->flags & WI_ICONIFIED)))
  1410.                 {
  1411.                     anz++;
  1412.                     opened_win[anz] = ic;
  1413.                     wind_close(window->handle);
  1414.                     if (window->flags & WI_ICONIFIED)
  1415.                     {
  1416.                         /*
  1417.                          * Iconify noch schnell aufheben. Schwachsinnige Größe macht nix,
  1418.                          * Fenster wird eh schon zu.
  1419.                          */
  1420.                         if (window->uniconify != NULL)
  1421.                             (*window->uniconify) (window);
  1422.                         wind_set(window->handle, WF_UNICONIFY, -1, -1, -1, -1);
  1423.                         window->flags &= ~WI_ICONIFIED;
  1424.                         if (window->class == CLASS_EDIT)
  1425.                             window->flags |= WI_MOUSE;
  1426.                     }
  1427.                     wind_delete(window->handle);    /* Fenster entgültig löschen */
  1428.                     window->handle = NO_HANDLE;
  1429.                     window->opened = 0;
  1430.                 }
  1431.         }
  1432.     }
  1433.     opened_win[0] = anz;
  1434.  
  1435.     /*
  1436.      * Nachdem nun alle anderen Fenster geschlossen wurden, wird ein
  1437.      * neues Fenster geöffnet. Etwas    umständlich, aber 'open_window' macht
  1438.      * viel zuviele Dinge mit dem Fenster, die ggf. gar nicht funken.
  1439.      */
  1440.     icon_win = create_window((NAME|MOVER), CLASS_ICON, 0, crt_wicon);
  1441.     icon_win->handle = wind_create((NAME|MOVER), desk.x, desk.y, desk.w, desk.h);
  1442.     set_wname(icon_win, " qed ");
  1443.     iconify_window(icon_win, new, TRUE);    /* Als Icon anmelden und öffnen! */
  1444.     bottom_window(icon_win, WM_BOTTOMED);    /* Icon nach hinten! */
  1445.     enable_menu(FALSE);                            /* Menu abschalten */
  1446.     all_iconified = TRUE;
  1447. }
  1448.  
  1449.  
  1450. VOID        uniconify_window(WINDP window, CONST RECT *new)
  1451. {
  1452.     WORD    i;
  1453.     RECT    r;
  1454.  
  1455.     if (all_iconified)
  1456.     {
  1457.         wind_close(icon_win->handle);    /* Icon schließen */
  1458.         wind_set(icon_win->handle, WF_UNICONIFY, -1, -1, -1, -1);
  1459.         destruct_window(icon_win);        /* und entgültig löschen */
  1460.         enable_menu(TRUE);                /* Menu wieder an */
  1461.         all_iconified = FALSE;
  1462.  
  1463.         i = 1;                                /* und alle Fenster wieder öffnen */
  1464.         while (i <= opened_win[0])
  1465.         {
  1466.             window = get_window(opened_win[i]);
  1467.             open_window(window);
  1468.             i++;
  1469.         }
  1470.     }
  1471.     else if (window != NULL && (window->flags & WI_ICONIFIED))
  1472.     {
  1473.         if (window->uniconify != NULL)
  1474.             (*window->uniconify) (window);
  1475.  
  1476.         wind_calc(WC_BORDER, window->kind,
  1477.                         window->work.x, window->work.y, window->work.w, window->work.h,
  1478.                         &r.x, &r.y, &r.w, &r.h);
  1479.  
  1480.         /* Wurde Font gewechselt während Fenster iconifiziert? */
  1481.         if (window->old_size.w != r.w)
  1482.             new = &r;
  1483.  
  1484.         if (new == NULL)
  1485.             wind_set(window->handle, WF_UNICONIFY, window->old_size.x, window->old_size.y,
  1486.                                                                 window->old_size.w, window->old_size.h);
  1487.         else
  1488.             wind_set(window->handle, WF_UNICONIFY, new->x, new->y, new->w, new->h);
  1489.  
  1490.         window->flags &= ~WI_ICONIFIED;
  1491.         if (window->class == CLASS_EDIT)
  1492.             window->flags |= WI_MOUSE;
  1493.         window->opened = 1;
  1494.         top_window(window);
  1495.     }
  1496. }
  1497.  
  1498. /***************************************************************************/
  1499. /* Zeichensatz wurde geändert                                                                */
  1500. /***************************************************************************/
  1501.  
  1502. GLOBAL VOID do_font_change(WINDP window)
  1503. {
  1504.     RECT    r;
  1505.  
  1506.     if (window->flags & WI_FONTSIZE)
  1507.     {
  1508.         window->xfac = gl_wchar;
  1509.         window->yfac = gl_hchar;
  1510.  
  1511.         r.x = window->work.x;
  1512.         r.y = window->work.y;
  1513.         r.w = window->work.w;
  1514.         r.h = gl_hchar * window->w_hight;
  1515.         if ((r.h + r.y) > desk.h)
  1516.             r.h = desk.h - r.y;
  1517.         size_window(window, &r, FALSE);
  1518.         redraw_window(window, &window->work);
  1519.     }
  1520. }
  1521.  
  1522. /***************************************************************************/
  1523. /* Klicken in das Fensterinnere                                                            */
  1524. /***************************************************************************/
  1525.  
  1526. VOID click_window (WINDP window, MKINFO *mk)
  1527. {
  1528.     if (window!=NULL)
  1529.     {
  1530.         if (window->click!=NULL)
  1531.             (*window->click) (window, mk);
  1532.         else
  1533.             unclick_window ();                     /* Deselektieren */
  1534.     }
  1535. } /* click_window */
  1536.  
  1537. /***************************************************************************/
  1538.  
  1539. VOID unclick_window (VOID)
  1540. {
  1541.     if (sel_window!=NULL && sel_window->unclick!=NULL)
  1542.         (*sel_window->unclick) (sel_window);
  1543.     sel_window = NULL;
  1544.     setclr (sel_objs);
  1545. } /* unclick_window */
  1546.  
  1547. /***************************************************************************/
  1548. /* Taste für ein Fenster                                                                    */
  1549. /***************************************************************************/
  1550.  
  1551. BOOLEAN key_window (WINDP window, MKINFO *mk)
  1552. {
  1553.     if (window->key!=NULL)
  1554.         return ((*window->key) (window, mk));
  1555.     return (FALSE);
  1556. } /* key_window */
  1557.  
  1558.  
  1559. /***************************************************************************/
  1560. /* Scroll- und Löschroutinen                                                                */
  1561. /***************************************************************************/
  1562.  
  1563. VOID scroll_vertical (CONST RECT *area, WORD delta)
  1564. /* Die Maus ist schon aus, keine Überprüfung auf Bildschirmgrenzen */
  1565. {
  1566.     MFDB    s, d;
  1567.     WORD    xy[8];
  1568.  
  1569.     rect2array (area, xy);
  1570.     xy[4] = xy[0];
  1571.     xy[5] = xy[1]-delta;
  1572.     xy[6] = xy[2];
  1573.     xy[7] = xy[3]-delta;
  1574.  
  1575.     s.fd_addr = d.fd_addr = NULL;                            /* Erzwinge Bildschirmadresse */
  1576.     vro_cpyfm (vdi_handle, S_ONLY, xy, &s, &d);        /* Eigentliches Scrolling */
  1577. } /* scroll_vertical */
  1578.  
  1579. /***************************************************************************/
  1580.  
  1581. VOID clr_area (CONST RECT *area)
  1582. {
  1583.     WORD xy[4];
  1584.  
  1585.     rect2array (area, xy);                                    /* Bereich setzen */
  1586.     if (fill_color!=WHITE)
  1587.     {
  1588.         vsf_color(vdi_handle,WHITE);
  1589.         fill_color = WHITE;
  1590.     }
  1591.     vr_recfl (vdi_handle, xy);                                /* Bereich löschen */
  1592. } /* clr_area */
  1593.  
  1594. /***************************************************************************/
  1595. /* Initialisieren des Moduls                                                                */
  1596. /***************************************************************************/
  1597.  
  1598. VOID init_windows (VOID)
  1599. {
  1600.     WINDP    window;
  1601.     WORD    i, *ptr;
  1602.  
  1603.     sel_window = NULL;                                    /* Kein Fenster angewählt */
  1604.     setclr (sel_objs);                                    /* Keine Objekte selektiert */
  1605.  
  1606.     used_list = NULL;
  1607.     age = 0;
  1608.     ptr = (WORD*)&windrec[MAX_WINDOW];                /* letzen (von hinten) löschen */
  1609.     for (i= (short) sizeof(WINDOW)/2; (--i)>=0; )
  1610.         *(--ptr) = 0;
  1611.     free_list = window = &windrec[0];
  1612.     for (i=MAX_WINDOW-1; (--i)>=0; window++)
  1613.     {
  1614.         COPYW(window,ptr, (short)sizeof(WINDOW));
  1615.         window->age = age++;
  1616.         window->next = &window[1];
  1617.     }
  1618.     window->age = age++;
  1619.     window->next = NULL;
  1620.  
  1621. } /* init_windows */
  1622.